package cn.xu.tool.big.a.compments;

import cn.xu.tool.big.a.dto.TotalReturn;
import cn.xu.tool.big.a.dto.TradeRecord;
import org.apache.commons.lang3.time.DateUtils;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.annotations.XYPointerAnnotation;
import org.jfree.chart.annotations.XYTextAnnotation;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.TextAnchor;
import org.jfree.data.time.Day;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;
import org.jfree.data.xy.XYDataset;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.*;

/**
 * 类名: ReportC
 * 描述: TODO
 * 作者: ClarkXu clark2021@qq.com
 * 日期: 2025/7/8
 */
public class ReportCp {

    private final static String parentPath = "D:\\work\\code\\clark\\gitee\\big_a\\datas";

    public static void createAssetsReport(List<TradeRecord> records, TotalReturn totalReturn) throws ParseException, IOException {
        // 步骤1：解析原始数据
        // 步骤2：创建数据集
        XYDataset dataset = createDataset(records, totalReturn);
        // 步骤3：创建图表
        String start = records.get(0).getDate().replaceAll("-", "");
        String end = records.get(records.size()-1).getDate().replaceAll("-", "");
        String title = "账户资产变动趋势（"+start+"-"+end+"）";
        JFreeChart chart = createChart(dataset, title);
        // 步骤4：添加买卖点标注
        addTradeAnnotations(chart.getXYPlot(), records);
        // 步骤5：应用中文主题
        applyChineseTheme(chart);

        // 步骤6：保存和显示图表
        saveAndDisplayChart(chart);
    }



    private static void applyChineseTheme(JFreeChart chart) {
        // 设置全局字体（在创建图表前调用）
        Font chartFont = new Font("Microsoft YaHei", Font.PLAIN, 12);
        // 防止中文显示为方框的关键设置
        System.setProperty("java.awt.headless", "false"); // 可选，解决无头环境问题

        // 设置所有字体
        StandardChartTheme theme = (StandardChartTheme) StandardChartTheme.createJFreeTheme();
        theme.setExtraLargeFont(new Font("Microsoft YaHei", Font.BOLD, 20));     // 标题
        theme.setLargeFont(new Font("Microsoft YaHei", Font.BOLD, 15));         // 图例
        theme.setRegularFont(new Font("Microsoft YaHei", Font.PLAIN, 13));      // 常规
        theme.setSmallFont(new Font("Microsoft YaHei", Font.PLAIN, 11));         // 标签
        theme.apply(chart); // 应用主题
    }

    // 解析输入数据
    private static List<TradeRecord> parseInputData() {
        List<TradeRecord> records = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        // 实际实现中这里应该是解析用户输入数据的逻辑
        // 伪代码：for each line in inputData: parse and create TradeRecord
        return records;
    }

    // 准备图表数据集
    private static XYDataset createDataset(List<TradeRecord> records, TotalReturn totalReturn) throws ParseException {
        StringBuilder sb = new StringBuilder();
        sb.append("初始资金: ￥" + totalReturn.getInitialCapital()).append(" ");
        sb.append("最终资金: ￥" + totalReturn.getFinalCapital()).append(" ");
        sb.append("总收益率: " + totalReturn.getReturnRate()).append(" ");
        sb.append("交易次数: " + totalReturn.getTradeCount());
        TimeSeries assetSeries = new TimeSeries(sb.toString());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
        for (TradeRecord record : records) {
            Date date = sdf.parse(record.getDate());
            assetSeries.add(new Day(date), record.getTotalAsset());
        }

        TimeSeriesCollection dataset = new TimeSeriesCollection();
        dataset.addSeries(assetSeries);
        return dataset;
    }

    // 创建基础图表
    private static JFreeChart createChart(XYDataset dataset, String title) {
        JFreeChart chart = ChartFactory.createTimeSeriesChart(
                title,
                "日期",
                "资产金额",
                dataset,
                true,
                true,
                false
        );

        XYPlot plot = chart.getXYPlot();

        // 优化线条样式
        XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer(true, false);
        renderer.setSeriesPaint(0, new Color(30, 144, 255)); // 深蓝色资产曲线
        renderer.setSeriesStroke(0, new BasicStroke(2.0f));
        plot.setRenderer(renderer);

        // 设置时间轴格式
        DateAxis dateAxis = (DateAxis) plot.getDomainAxis();
        dateAxis.setDateFormatOverride(new SimpleDateFormat("yyyy/MM"));
        dateAxis.setVerticalTickLabels(true);
        // 智能缩放时间轴
        dateAxis.setTickMarkPosition(DateTickMarkPosition.MIDDLE);
        dateAxis.setVerticalTickLabels(true);

        // 设置金额格式
        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setNumberFormatOverride(NumberFormat.getCurrencyInstance(Locale.CHINA));

        // 添加网格线
        plot.setDomainGridlinePaint(new Color(200, 200, 200, 100));
        plot.setRangeGridlinePaint(new Color(200, 200, 200, 100));
        plot.setBackgroundPaint(Color.WHITE);
        plot.setDomainGridlinesVisible(true);
        plot.setRangeGridlinesVisible(true);

        return chart;
    }

    // 添加买卖点标注
    private static void addTradeAnnotations(XYPlot plot, List<TradeRecord> records) throws ParseException {
        Map<String, List<XYTextAnnotation>> dateAnnotations = new HashMap<>();
        double maxY = 0;
        double minY = Double.MAX_VALUE;

        // 计算Y轴范围
        for (TradeRecord record : records) {
            if (record.getTotalAsset() > maxY) maxY = record.getTotalAsset();
            if (record.getTotalAsset() < minY) minY = record.getTotalAsset();
        }
        double range = maxY - minY;

        // 创建所有买卖点标注
        for (TradeRecord record : records) {
            if ("买入".equals(record.getOperation()) || "卖出".equals(record.getOperation())) {
                String dateStr = record.getDate().substring(5);

                // 创建标注
                XYTextAnnotation annotation = createTradeAnnotation(record);

//                annotation.setBackgroundPaint(new Color(255, 255, 255, 180)); // 半透明白底
//                annotation.setOutlinePaint(new Color(0, 0, 0, 100)); // 添加细边框

                // 检查同一天是否有多个交易
                if (dateAnnotations.containsKey(dateStr)) {
                    List<XYTextAnnotation> sameDay = dateAnnotations.get(dateStr);
                    sameDay.add(annotation);

                    // 计算垂直偏移量以避免重叠
                    int index = sameDay.size() - 1;
                    double yOffset = range * 0.10 * (index % 2 == 0 ? 1 : -1) * Math.ceil(index/2.0);
                    annotation.setY(yOffset);

                    // 新增水平偏移量
                    double xOffset = 0;
                    for (int i = 0; i < sameDay.size(); i++) {
                        if (i > 0) {
                            // 水平偏移量为前一个标注宽度的1.2倍
                            xOffset += sameDay.get(i-1).getText().length() * 6;
                        }
                        annotation.setX(xOffset);
                    }

                    int fontSize = Math.max(8, 12 - sameDay.size() * 2);
                    annotation.setFont(new Font("Microsoft YaHei", Font.BOLD, fontSize));
                } else {
                    dateAnnotations.put(dateStr, new ArrayList<>(Collections.singletonList(annotation)));
                }

                plot.addAnnotation(annotation);
            }
        }


        // 添加峰值标记
        addPeakAnnotation(plot, records);
    }

    private final static double[] pi_ary = {Math.PI/2,Math.PI/2*3};// 90度角 270度

    private static int pi_pointer = 0;

    // 创建单个交易标注
    private static XYPointerAnnotation createTradeAnnotation(TradeRecord record) throws ParseException {

        XYPointerAnnotation pointerAnn = new XYPointerAnnotation(
                String.format("%s %s\n¥%.2f",
                        record.getDate().substring(5).replaceAll("-", "/"),
                        record.getOperation().charAt(0),
                        record.getPrice()),
                DateUtils.parseDate(record.getDate(), "yyyy-MM-dd").getTime(),
                record.getTotalAsset(),
                pi_ary[pi_pointer]// 随机角度方向
        );
        pi_pointer ++;
        if(pi_pointer==pi_ary.length){
            pi_pointer = 0;
        }
        pointerAnn.setArrowLength(25);
        pointerAnn.setLabelOffset(20);// 文本与箭头的距离[2](@ref)

        // 设置样式
        pointerAnn.setFont(new Font("Microsoft YaHei", Font.BOLD, 10));
        pointerAnn.setBackgroundPaint(new Color(255, 255, 255, 220));
        pointerAnn.setTextAnchor(TextAnchor.TOP_CENTER);

        // 设置交易类型颜色
        if ("买入".equals(record.getOperation())) {
            pointerAnn.setPaint(new Color(50, 168, 82)); // 绿色
        } else {
            pointerAnn.setPaint(new Color(220, 53, 69)); // 红色
        }
        pointerAnn.setArrowPaint(pointerAnn.getPaint());

        return pointerAnn;
    }

    // 添加峰值标记
    private static void addPeakAnnotation(XYPlot plot, List<TradeRecord> records) throws ParseException {
        // 找到最大资产值
        TradeRecord peak = null;
        for (TradeRecord record : records) {
            if (peak == null || record.getTotalAsset() > peak.getTotalAsset()) {
                peak = record;
            }
        }

        if (peak != null) {
            XYTextAnnotation peakAnnotation = new XYTextAnnotation(
                    String.format("峰值: %.2f\n%s",
                            peak.getTotalAsset(),
                            peak.getDate()),
                    DateUtils.parseDate(peak.getDate(), "yyyy-MM-dd").getTime(),
                    peak.getTotalAsset() * 1.05
            );

            peakAnnotation.setFont(new Font("Microsoft YaHei", Font.BOLD, 12));
            peakAnnotation.setPaint(new Color(255, 193, 7)); // 金色
            peakAnnotation.setTextAnchor(TextAnchor.BOTTOM_CENTER);
            peakAnnotation.setBackgroundPaint(new Color(33, 37, 41, 200)); // 深色半透明背景

            // 添加指向峰值的箭头
            XYPointerAnnotation pointer = new XYPointerAnnotation("",
                    DateUtils.parseDate(peak.getDate(), "yyyy-MM-dd").getTime(),
                    peak.getTotalAsset() * 1.03,
                    Math.PI * 1.5
            );
            pointer.setTipRadius(0.0);
            pointer.setBaseRadius(60.0);
            pointer.setArrowLength(12);
            pointer.setArrowWidth(6);
            pointer.setPaint(new Color(255, 193, 7));
//            pointer.setStroke(new BasicStroke(1.5f));

            plot.addAnnotation(peakAnnotation);
            plot.addAnnotation(pointer);
        }
    }


    // 保存和显示图表
    private static void saveAndDisplayChart(JFreeChart chart) throws IOException {
        // 保存为PNG文件
        ChartUtils.saveChartAsPNG(
                new File(parentPath+"/backtest/"+"account_trend.png"),
                chart,
                2240, 1400
        );
    }



}
